import React, { useEffect, useRef, useState, useImperativeHandle, forwardRef } from 'react';
import BpmnModeler from 'bpmn-js/lib/Modeler';
// 以下为bpmn工作流绘图工具的样式
import 'bpmn-js/dist/assets/diagram-js.css' // 左边工具栏以及编辑节点的样式
import 'bpmn-js-bpmnlint/dist/assets/css/bpmn-js-bpmnlint.css' // bpmnlint

import lintModule from 'bpmn-js-bpmnlint';
import * as bpmnlintConfig from './packed-config';


import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
import 'bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css' // 右边工具栏样式

//為右邊屬性
import propertiesPanelModule from 'bpmn-js-properties-panel'
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'
import {Button, Col, Divider, Input, Modal, Row, Space, List, message, Table, Form} from 'antd';
import customTranslateModule from '../BpmnEditor/Modeler/customTranslate';
import getDefaultXml from '../BpmnEditor/sources/xml';
import {Link} from "react-router-dom";



import {
    SearchOutlined,
    ZoomInOutlined,
    ZoomOutOutlined,
    SaveOutlined,
    ExportOutlined,
    VideoCameraOutlined,
    UploadOutlined,
    TagOutlined,
    CheckOutlined,
IssuesCloseOutlined
} from '@ant-design/icons';

import {addByString, getDefinitions} from "../api/workflow";
import { getUserList } from "../api/Security";
import {withRouter} from 'react-router-dom';
import WorkflowDesign from "./workflowDesign";


export default function BpmnDesign() {
    // let bpmnModeler=null;
    //const  [mybpmnModeler, setMybpmnModeler] =  useState(null); //所有用户列表 供选择人使用
    const modelerRef = useRef(null);

    const  [users, setUsers] =  useState([]); //所有用户列表 供选择人使用
    //
    //控制可见性
    const  [modalvisiable, setModalvisiable] =  useState(false);  //modal可见性
    // const  [selectedRowKeys,setSelectedRowKeys] =  useState([]);  //选择的人
    const  [selectedUserId,setSelectedUserId] =  useState(-1);  //选择的人
    const  [selectedUserName,setSelectedName] =  useState("");  //选择的人的名字
    const [selectElement,setSelectElement] =  useState(null);  //选择usertask节点
    const [activeNodeEle, setActiveNode] = useState(null);  //代替上一行的内容
    const [lintActive,setLintActive]= useState(false);


    useEffect(()=>{
        initBpmn();
    },[])

    // var customTranslateModule = {
    //     translate: [ 'value', customTranslate ]
    // };

    const columns = [
        {
            title: 'id',
            dataIndex: 'userid',
            key: 'userid',
        },
        {
            title: '用户名',
            dataIndex: 'name',
            key: 'name',
        },
        {
            title: '启用状态',
            dataIndex: 'userFlag',
            key: 'userFlag',
        }
    ];


const  initBpmn=()=>{

    modelerRef.current =
        new BpmnModeler({
            container:"#canvas",
            //添加控制板
            propertiesPanel: {
                parent: '#js-properties-panel'
            },
            additionalModules: [
                // 右边的属性栏
                customTranslateModule,
                propertiesProviderModule,
                propertiesPanelModule,
                lintModule
            ],
            linting: {
                bpmnlint: bpmnlintConfig,
                active:false  //如果要检查 要配置这里
            },
            moddleExtensions: {
                camunda: camundaModdleDescriptor
            },
            height:'100vh'
        })

    const logo = document.querySelector('.bjs-powered-by');
    const bpmnContainer = document.querySelector('.bjs-container');
    if (bpmnContainer && logo) {
        bpmnContainer.removeChild(logo);
    }
    renderDiagram();
    getUsers();  //获取全部用户信息 为选择用户做准备
    addListener();  //模型上追加监听器
}


    const initActiveNode = () => {
        const canvas = modelerRef.current.get('canvas');
        const rootElement = canvas.getRootElement();
        setActiveNode(rootElement);
    };

// const createBpmnDiagram= async ()=>{
//         let xmlStr2="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:omgdi=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:omgdc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:camunda=\"http://camunda.org/schema/1.0/bpmn\" xmlns:activiti=\"http://activiti.org/bpmn\" xmlns:tns=\"http://www.activiti.org/test\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" id=\"m1605802588480\" name=\"\" targetNamespace=\"http://www.activiti.org/test\">\\n  <process id=\"Process_1\" isExecutable=\"true\">\\n    <startEvent id=\"StartEvent_1y45yut\" name=\"开始\">\\n      <outgoing>Flow_0jfbnmb</outgoing>\\n    </startEvent>\\n    <userTask id=\"Activity_1w1vj9r\" name=\"username1\" activiti:formKey=\"kkk\" activiti:assignee=\"1\" activiti:candidateUsers=\"candidateUsers\" activiti:candidateGroups=\"candidateGroups\">\\n      <extensionElements>\\n        <activiti:formData>\\n          <activiti:formProperty id=\"formProperty_3slq4mu\" />\\n        </activiti:formData>\\n        <activiti:properties>\\n          <activiti:property />\\n        </activiti:properties>\\n      </extensionElements>\\n      <incoming>Flow_0jfbnmb</incoming>\\n      <outgoing>Flow_1nolku9</outgoing>\\n    </userTask>\\n    <sequenceFlow id=\"Flow_0jfbnmb\" sourceRef=\"StartEvent_1y45yut\" targetRef=\"Activity_1w1vj9r\" />\\n    <endEvent id=\"Event_0ahqy2x\" name=\"e\">\\n      <incoming>Flow_1nolku9</incoming>\\n    </endEvent>\\n    <sequenceFlow id=\"Flow_1nolku9\" sourceRef=\"Activity_1w1vj9r\" targetRef=\"Event_0ahqy2x\" />\\n  </process>\\n  <bpmndi:BPMNDiagram id=\"BpmnDiagram_1\">\\n    <bpmndi:BPMNPlane id=\"BpmnPlane_1\" bpmnElement=\"Process_1\">\\n      <bpmndi:BPMNEdge id=\"Flow_0jfbnmb_di\" bpmnElement=\"Flow_0jfbnmb\">\\n        <omgdi:waypoint x=\"188\" y=\"120\" />\\n        <omgdi:waypoint x=\"300\" y=\"120\" />\\n      </bpmndi:BPMNEdge>\\n      <bpmndi:BPMNEdge id=\"Flow_1nolku9_di\" bpmnElement=\"Flow_1nolku9\">\\n        <omgdi:waypoint x=\"400\" y=\"120\" />\\n        <omgdi:waypoint x=\"542\" y=\"120\" />\\n      </bpmndi:BPMNEdge>\\n      <bpmndi:BPMNShape id=\"StartEvent_1y45yut_di\" bpmnElement=\"StartEvent_1y45yut\">\\n        <omgdc:Bounds x=\"152\" y=\"102\" width=\"36\" height=\"36\" />\\n        <bpmndi:BPMNLabel>\\n          <omgdc:Bounds x=\"160\" y=\"145\" width=\"22\" height=\"14\" />\\n        </bpmndi:BPMNLabel>\\n      </bpmndi:BPMNShape>\\n      <bpmndi:BPMNShape id=\"Activity_1w1vj9r_di\" bpmnElement=\"Activity_1w1vj9r\">\\n        <omgdc:Bounds x=\"300\" y=\"80\" width=\"100\" height=\"80\" />\\n      </bpmndi:BPMNShape>\\n      <bpmndi:BPMNShape id=\"Event_0ahqy2x_di\" bpmnElement=\"Event_0ahqy2x\">\\n        <omgdc:Bounds x=\"542\" y=\"102\" width=\"36\" height=\"36\" />\\n        <bpmndi:BPMNLabel>\\n          <omgdc:Bounds x=\"557\" y=\"145\" width=\"7\" height=\"14\" />\\n        </bpmndi:BPMNLabel>\\n      </bpmndi:BPMNShape>\\n    </bpmndi:BPMNPlane>\\n  </bpmndi:BPMNDiagram>\\n</definitions>\n";
//          mybpmnModeler.importXML(xmlStr2);
//          const diagramXML = getDefaultXml();
//          //this.renderDiagram(diagramXML);
//         try {
//         //const result = await bpmnModeler.importXML(xmlStr2);
//     } catch (e) {
//         console.error(e);
//     }
//     }


    const renderDiagram = () => {
        //let XML="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:omgdi=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:omgdc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:camunda=\"http://camunda.org/schema/1.0/bpmn\" xmlns:activiti=\"http://activiti.org/bpmn\" xmlns:tns=\"http://www.activiti.org/test\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" id=\"m1605802588480\" name=\"\" targetNamespace=\"http://www.activiti.org/test\">\\n  <process id=\"Process_1\" isExecutable=\"true\">\\n    <startEvent id=\"StartEvent_1y45yut\" name=\"开始\">\\n      <outgoing>Flow_0jfbnmb</outgoing>\\n    </startEvent>\\n    <userTask id=\"Activity_1w1vj9r\" name=\"username1\" activiti:formKey=\"kkk\" activiti:assignee=\"1\" activiti:candidateUsers=\"candidateUsers\" activiti:candidateGroups=\"candidateGroups\">\\n      <extensionElements>\\n        <activiti:formData>\\n          <activiti:formProperty id=\"formProperty_3slq4mu\" />\\n        </activiti:formData>\\n        <activiti:properties>\\n          <activiti:property />\\n        </activiti:properties>\\n      </extensionElements>\\n      <incoming>Flow_0jfbnmb</incoming>\\n      <outgoing>Flow_1nolku9</outgoing>\\n    </userTask>\\n    <sequenceFlow id=\"Flow_0jfbnmb\" sourceRef=\"StartEvent_1y45yut\" targetRef=\"Activity_1w1vj9r\" />\\n    <endEvent id=\"Event_0ahqy2x\" name=\"e\">\\n      <incoming>Flow_1nolku9</incoming>\\n    </endEvent>\\n    <sequenceFlow id=\"Flow_1nolku9\" sourceRef=\"Activity_1w1vj9r\" targetRef=\"Event_0ahqy2x\" />\\n  </process>\\n  <bpmndi:BPMNDiagram id=\"BpmnDiagram_1\">\\n    <bpmndi:BPMNPlane id=\"BpmnPlane_1\" bpmnElement=\"Process_1\">\\n      <bpmndi:BPMNEdge id=\"Flow_0jfbnmb_di\" bpmnElement=\"Flow_0jfbnmb\">\\n        <omgdi:waypoint x=\"188\" y=\"120\" />\\n        <omgdi:waypoint x=\"300\" y=\"120\" />\\n      </bpmndi:BPMNEdge>\\n      <bpmndi:BPMNEdge id=\"Flow_1nolku9_di\" bpmnElement=\"Flow_1nolku9\">\\n        <omgdi:waypoint x=\"400\" y=\"120\" />\\n        <omgdi:waypoint x=\"542\" y=\"120\" />\\n      </bpmndi:BPMNEdge>\\n      <bpmndi:BPMNShape id=\"StartEvent_1y45yut_di\" bpmnElement=\"StartEvent_1y45yut\">\\n        <omgdc:Bounds x=\"152\" y=\"102\" width=\"36\" height=\"36\" />\\n        <bpmndi:BPMNLabel>\\n          <omgdc:Bounds x=\"160\" y=\"145\" width=\"22\" height=\"14\" />\\n        </bpmndi:BPMNLabel>\\n      </bpmndi:BPMNShape>\\n      <bpmndi:BPMNShape id=\"Activity_1w1vj9r_di\" bpmnElement=\"Activity_1w1vj9r\">\\n        <omgdc:Bounds x=\"300\" y=\"80\" width=\"100\" height=\"80\" />\\n      </bpmndi:BPMNShape>\\n      <bpmndi:BPMNShape id=\"Event_0ahqy2x_di\" bpmnElement=\"Event_0ahqy2x\">\\n        <omgdc:Bounds x=\"542\" y=\"102\" width=\"36\" height=\"36\" />\\n        <bpmndi:BPMNLabel>\\n          <omgdc:Bounds x=\"557\" y=\"145\" width=\"7\" height=\"14\" />\\n        </bpmndi:BPMNLabel>\\n      </bpmndi:BPMNShape>\\n    </bpmndi:BPMNPlane>\\n  </bpmndi:BPMNDiagram>\\n</definitions>\n";
       const XML = getDefaultXml();
        modelerRef.current.importXML(XML, (err) => {
            if (err) {
                Modal.error({ title: 'XML解析失败' });
                return false;
            }
            initActiveNode();
            return true;
        });
    };


  const  getUsers=()=>{
      getUserList().then(
          (res) => {
              setUsers(res.data);
          },
          (error) => {
              console.log("get UserList failed!");
          }
      );
  }

  //追加监听器
  const addListener=()=>{
      addModelerListener();
      addEventBusListener();
  }




    const addEventBusListener=()=>{
        const bpmnjs = modelerRef.current;
        const eventBus = bpmnjs.get('eventBus');
        eventBus.on('element.click', function(e) {
            elementClick(e);
        });
    }


    const addModelerListener = () => {
        const bpmnjs = modelerRef.current;
        //const events = ['element.click', 'element.changed'];
        const events = ['element.click'];
        events.forEach((eventType) => {
            bpmnjs.on(eventType, (e) => {
                const { element } = e;
                const { type } = element;
                if (type !== 'label') {
                    setActiveNode(element);
                }
            });
        });
    };

    // const addModelerListener=()=>{
    //   // bpmnModeler.on('element.click', e => {
    //   //       console.log('modelerListener', e);
    //   //   });
    // }


   const elementClick=(e)=> {
       const bpmnjs = modelerRef.current;
      //  let modeling = bpmnjs.get('modeling');
        if (e.element.businessObject.$type === 'bpmn:StartEvent') {
            console.log(
                '这是一个开始节点',
                e.element.businessObject.id,
                e.element.businessObject.$type,
                e.element.businessObject.name
            );
            // 修改节点ID
            // modeling.updateProperties(e.element, {
            //     id: 'StartEvent_ops_coffee'
            // });
        }
        if (e.element.businessObject.$type === 'bpmn:UserTask') {
            console.log(
                '这是一个用户节点',
                e.element.businessObject.id,
                e.element.businessObject.$type,
                e.element.businessObject.name
            );
            //this.selectElement = e.element;
            setSelectElement(e.element);    //选中的元素
            //this.setColumnDialogVisible = true;
            //console.log(this.selectElement);
            //修改节点名称
            // modeling.updateProperties(e.element, {
            //   name: this.user.id
            // });
        }else{
            setSelectElement(null);
        }
    }

    const container = {
        width: "100%",
        height:"100%"
    };
    const bpmnDesignClass = {
        minHeight: "100vh",
    };

    const properties_panel = {
        // position:"absolute",
        // right:"0",
        // top:"0",
        // width:"300px"
    };



//get xml
    const getBpmnXML = async () => {
        const bpmnModeler = modelerRef.current;
        return new Promise((resolve, reject) => {
            bpmnModeler.saveXML({ format: true }, (err, xml) => {
                if (err) {
                    reject(err);
                }
                resolve(xml);
            });
        });
    };

    const onSave = async () => {
        const xml = await getBpmnXML();
        addByString(xml).then(
            (res) => {
                message.success('保存成功');
            },
            (error) => {
                message.error('failed');
                console.log("get response failed!");
            }
        );
    };
    const saveDiagram = () => {
       //verify  by lint?
        const bpmnModeler = modelerRef.current;
        const linting = bpmnModeler.get('linting');
        const { _button, _active } = linting;
        if (!_active) {
            linting.toggle();
            message.success('开启流程检查！');
            return;
        }
        const { innerText } = _button;
        const errorTexts = Number(innerText.split(' Errors')[0]);
        if (errorTexts > 0) {
            message.success('流程有错误，无法保存，请检查！');
            return;
        }



        onSave().then(
            console.log("saveDiagram!")
        );
    };
//选择雇员
    const SearchEmp= () => {
        if(selectElement==null){
          setModalvisiable(false);
            setSelectedUserId(-1);
      }else {
          setModalvisiable(true);

          setSelectedUserId(-1);

      }
    };

    const  returnDefList=()=>{
        // BrowserRouter.context.routes.push('/main/tool/processDef');
        //history.push('/main/tool/processDef')
    }


    const  cancelModal=()=>{
       setModalvisiable(false);
    }

    const onSelectChange = selectedRowKeys => {
        console.log('selectedRowKeys changed: ', selectedRowKeys);
        //setSelectedRowKeys(selectedRowKeys );
    };

    // const rowSelection = {
    //     selectedRowKeys,
    //     onChange: onSelectChange,
    // };

    const  rowSelection = {
        onChange: (selectedRowKeys, selectedRows) => {
             console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
        },
        onSelect: (record, selected, selectedRows) => {
            if(selected){
                // this.setState({
                //     selectedUserId: record.userid,
                // });
                setSelectedUserId( record.userid);
                //setSelectedName( record.name);
            }
        },
    };


//选择确定
    const selConfirm = ()=>{
        const bpmnModeler = modelerRef.current;
        //选择的用户
         if (selectedUserId==-1){
            message.info("请选择一个用户")
            return;
        }

        let modeling = bpmnModeler.get('modeling');
        modeling.updateProperties(selectElement, {
            name: selectedUserId+"",
            //执行人
            assignee: selectedUserId+"" ,
            //候选人
           // candidateUsers:'candidateUsers',
            //候选组
           // candidateGroups:'candidateGroups'
        });
        setModalvisiable(false);
    };

    const  checkBPMN=()=>{
        const bpmnModeler = modelerRef.current;
        const linting = bpmnModeler.get('linting');
        const { _button, _active } = linting;
        if (!_active) {
            linting.toggle();
            message.success('开启流程检查！');
            return;
        }
    }

    const closeCheckBPMN=()=>{
        const bpmnModeler = modelerRef.current;
        const linting = bpmnModeler.get('linting');
        const { _button, _active } = linting;
        if (_active) {
            linting.toggle();
            message.success('关闭流程检查！');
            return;
        }
    }
return(
    <>
    <div className={bpmnDesignClass}>

        <Row justify={"center"}>
            <Button icon={<SearchOutlined/>} key={"SearchEmp"}
                    onClick={() => SearchEmp()}
            />
            <Button icon={<ZoomInOutlined />} key={"zoomin"}

            />
            <Button icon={<ZoomOutOutlined />} key={"zoomout"}/>
            <Button icon={<CheckOutlined />} key={"CheckOutlined"}
                    onClick={() => checkBPMN()}
            />
            <Button icon={ <IssuesCloseOutlined />} key={"IssuesCloseOutlined"}
                    onClick={() => closeCheckBPMN()}
            />



            <Button icon={<SaveOutlined />} key={"SaveOutlined"}
             onClick={() => saveDiagram()}
            />
            <Link to={"/main/tool/processDef"}>
                <Button icon={<ExportOutlined />} key={"ExportOutlined"}/>
            </Link>
        </Row>

        <Row>
        <Col span={18}>
            <div id="canvas" className={container}>
            </div>
        </Col>


        <Col span={6}>
            <div
                className={properties_panel}
                id="js-properties-panel"
                style={{ height: '100%' }}
            />
        </Col>

        </Row>
    </div>

        <Modal
            width={600}
            title="选择审批人"
            visible={modalvisiable}
            cancelText='返回'
            onCancel={cancelModal}
            footer={null}
        >
            <Table
                //rowKey={record => record.userid}
                     // rowSelection={rowSelection}

                     rowSelection={{
                         type: "radio",
                         ...rowSelection,
                     }}
                     rowKey="userid"
                     columns={columns}
                     dataSource={users} />

            <Row>
                <Col span={16}></Col>
                <Col span={3}><Button type="primary" onClick={selConfirm}>确定</Button></Col>
                <Col span={3}><Button onClick={cancelModal}>取消</Button></Col>
                <Col span={2}></Col>
            </Row>
        </Modal>


    </>
)
}


